// void setDefaultPresets() {
//   for (int idx = 0; idx < NUM_PRESETS; ++idx) {
//     for (int chan = 0; chan < NUM_CHANNELS; ++chan) {
//       //         Idx       chan       loOff   hiOff     midiCc  funct   wave    lfoBpm  midiTime
//       saveChannelPreset(idx,      chan,      0,      255,      0,      0,      0,      0,      0);
//     }
//   }
// }
// 
// void saveChannelPreset(int idx, int channel, int lowOffset, int hiOffset, int midiCC, int outputFunct, int wavetable, int lfoBpm, int midiTime) {
//   int offset = PRESET_OFFSET + (idx * PRESET_SIZE) + (channel * CHAN_PRESET_SIZE);
//   EEPROM.write(offset++, lowOffset);
//   EEPROM.write(offset++, hiOffset);
//   EEPROM.write(offset++, midiCC);
//   EEPROM.write(offset++, outputFunct);
//   EEPROM.write(offset++, wavetable);
//   EEPROM.write(offset++, lfoBpm);
//   EEPROM.write(offset++, midiTime);
// }
// 
// void loadPreset(int idx) {
//   int offset = idx * PRESET_SIZE;
//   for (int i = 0; i < PRESET_SIZE; ++i) {
//     presets[offset + i] = EEPROM.read(offset + i + PRESET_OFFSET);
//   }
// }
// 
// void loadPresets() {
//   for (int i = 0; i < NUM_PRESETS; ++i) {
//     loadPreset(i);
//   }
// }
// 
// void selectPreset(int idx) {
//   int presetOffset = idx * PRESET_SIZE;
//   topval[0] = presets[presetOffset];
//   topval[1] = presets[presetOffset + 1 * CHAN_PRESET_SIZE];
//   topval[2] = presets[presetOffset + 2 * CHAN_PRESET_SIZE];
//   bottomval[0] = presets[presetOffset + 1];
//   
//   // set current preset variable
// }

//void saveCurrentPreset() {
//  EEPROM.write(CURRENT_PRESET_ADDRESS, currentPreset);
//};
//
//int getCurrentPreset() {
//  return EEPROM.read(CURRENT_PRESET_ADDRESS);
//}

// this function will return the number of bytes currently free in RAM
int memoryTest() {
  int byteCounter = 0; // initialize a counter
  byte *byteArray; // create a pointer to a byte array
  // More on pointers here: http://en.wikipedia.org/wiki/Pointer#C_pointers

  // use the malloc function to repeatedly attempt allocating a certain number of bytes to memory
  // More on malloc here: http://en.wikipedia.org/wiki/Malloc
  while ( (byteArray = (byte*) malloc (byteCounter * sizeof(byte))) != NULL ) {
    byteCounter++; // if allocation was successful, then up the count for the next try
    free(byteArray); // free memory after allocating it
  }
  
  free(byteArray); // also free memory after the function finishes
  return byteCounter; // send back the highest number of bytes successfully allocated
}

//************************************************pedal functions*****************************
//***********user interface - select function**********

void Set_Functions(byte chan, byte line) {        // increments the case each time channel switch is hit 
  function[chan] = function[chan]++;              // cycles through output options
  if (function[chan] > 9) {
    function[chan] = 0;          //reset
  }
  swnum = 9;      // null switch
  Set_And_Restore(chan, line);
}
void Set_And_Restore(byte chan, byte line) {     //logic to assign output according to switch presses
//  disp_BPM();
  switch (function[chan]) {
      case 0:
      topval[chan] = old_topval[chan];          //save these while we go through waveforms, so they are not lost
      top_offset[chan] = true;                        //write to offset pots
      bottomval[chan] = old_bottomval[chan];    //may need their own variables, borrowed them from setting top and bottom offsets
      bottom_offset[chan] = true;
      functArr[chan] = &LEFT_PED;
      Serial2.print(line, DEC);
      Serial2.print(" Left Ped");
      clean[chan] = true;      //rub out this text when bargraph displays 
      disp_BPM();                         //need this one
      break;
      case 1:
      functArr[chan] = &LEFT_PED_INV;
      Serial2.print(line, DEC);
      Serial2.print(" INV Left Ped"); 
      clean[chan] = true;      //rub out this text when bargraph displays      
      disp_BPM();                          //need these other ones??
      break;
      case 2: 
      functArr[chan] = &RIGHT_PED;
      Serial2.print(line, DEC);
      Serial2.print(" Right Ped");
      clean[chan] = true;      //rub out this text when bargraph displays 
      disp_BPM();
      break;
      case 3:
      functArr[chan] = &RIGHT_PED_INV;
      Serial2.print(line, DEC);
      Serial2.print(" INV Right Ped");
      clean[chan] = true;      //rub out this text when bargraph displays 
      disp_BPM();
      break;
      case 4:
      old_topval[chan] = topval[chan];          //save these while we go through waveforms, so they are not lost
      old_bottomval[chan] = bottomval[chan];    //may need their own variables, borrowed them from setting top and bottom offsets
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &SQUARE_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Sqr   BPM:");
      disp_BPM();                            //need this one
      break;
      case 5:
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &TRI_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Tri   BPM:");
      disp_BPM();
      break;
      case 6:
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &SINE_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Sine  BPM:");
      disp_BPM();
      break;
      case 7:
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &SINE_EXP_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Sine1 BPM:");
      disp_BPM();
      break;
      case 8:
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &SAW_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Ramp  BPM:");
      disp_BPM();
      break;
      case 9:
      functArr[chan] = &WAVEOUT;
      waveArr[chan] = &SAW_REV_TABLE[0];
      HI_LOW_OFFSET[chan] = true;
      Serial2.print(line, DEC);
      Serial2.print(" LFO Saw   BPM:");
      disp_BPM();
      break;
    }
}
//***********user interface - upper button**********
void Upper_Button(byte chan, byte line, byte sw ) {

 if (HOLD_FLAG[chan] == false && Set_Lower == false && Set_Upper == false) {  // no hold or offset functions
          Serial2.print("?y");          //lock functions
          Serial2.print(chan, DEC);      // line or chan??? 
          Serial2.print("?x00");
          Lock_Functions(chan); 
        }
        else if (HOLD_FLAG[chan] == false && function[chan] > 3 && Set_Upper == true) {  //cancel the set upper function on wavetable
          Set_Upper = false;  
          blink_led[0] = false;
        }

        else if (HOLD_FLAG[chan] == false && function[chan] < 4 && Set_Upper == true) {       
          swnum = 9; 
          if (Save_Upper[chan] == false) {  //set upper first time through to select channel
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l");           
            Set_Upper_Offset_A(chan, line); 
            blink_led[sw] = true;
          }
          else {                          //second time through to save upper setting
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l"); 
            Set_Upper_Offset_B(chan, line); 
            blink_led[sw] = false;
          }
        }
}
        
//***********user interface - lower button**********
void Lower_Button(byte chan, byte line, byte sw ) {
 if (HOLD_FLAG[chan] == false && Set_Lower == false && Set_Upper == false) {    //no lock or offset functions
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l");                                             //set functions
          Set_Functions(chan, line); 
        }
        else if (HOLD_FLAG[chan] == false && Set_Lower == true && function[chan] > 3 ) {   //cancel set lower function on wavetable
          Set_Lower = false;   
          blink_led[2] = false;
        }

        else if (HOLD_FLAG[chan] == false && Set_Lower == true && function[chan] < 4 ) {
          swnum = 9; 
          if (Save_Lower[chan] == false) {  //first time through to select channel
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l"); 
            Set_Lower_Offset_A(chan, line);
            blink_led[sw] = true; 
          }
          else {                          //second time through to save lower setting
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l"); 
            Set_Lower_Offset_B(chan, line); 
            blink_led[sw] = false;
          }
        }
        else if (HOLD_FLAG[chan] == true) {    //restore channel function
            Serial2.print("?y");
            Serial2.print(chan, DEC);
            Serial2.print("?x00?l");
          Restore_Functions(chan, line); 
        }
      }



//***********user interface - lock and restore voltage output**********

void Lock_Functions(byte chan)            // holds the output voltage for expr pedal, upper and lower offsets for waveform
 {                      
  Serial2.print("H");
  swnum = 9;    //null switch  
  functArr[chan] = &HOLD_CHAN;
  HOLD_FLAG[chan] = true;                      // restore previous function instead of going through switch statement
  HI_LOW_OFFSET[chan] = false;
  if (function[chan] < 4) {                    // erases any text hanging around and displays graph
  disp_bargraph = true;
  BARGRAPH(chan);
  }
}
void Restore_Functions(byte chan , byte line)      // restores previous output functions and restores voltage output
  {
  swnum = 9;  //null switch
    //revert to last need more 
  HOLD_FLAG[chan] = false;
  HI_LOW_OFFSET[chan] = true;
  Set_And_Restore(chan, line); 
  }
 
 //***********user interface - set upper offset**********
  
void Set_Upper_Offset_A(byte chan, byte line)  {    // may want to incorporate upper and lower offsets  when seetting voltage levels for more accuracy
  blink_led[0] = false;
  Save_Upper[chan] = true;
  Serial2.print(line, DEC);
  Serial2.print(" CHAN to SAVE UP");       // almost works......
  if (function[chan] < 2)  {
    functArr[chan] = &LEFT_PED_UPPER_OFFSET;
  }
  else   {
    functArr[chan] = &RIGHT_PED_UPPER_OFFSET;
  }
//  old_bottomval[chan] = bottomval[chan];
//  bottomval[chan] = 0;
//  bottom_offset[chan] = true;
  topval[chan] = 255;
  top_offset[chan] = true; 
}

void Set_Upper_Offset_B(byte chan, byte line) {
  Save_Upper[chan] = false; 
//  Set_Upper = false; 
for (i=0; i < 4; i++) {                // make sure we clear all the states that set the upper and lower offsets
  if (Save_Upper[i] == true) {          // check its neighbors before clearing flag
  Set_Upper = true;
    break;
  }
  Set_Upper = false;
}
  Serial2.print(line, DEC);
  Serial2.print(" Upper Limit SAVED"); 
  clean[chan] = true;      //rub out this text when bargraph displays 
  switch (function[chan]) {
    case 0:  
       functArr[chan] = &LEFT_PED;
       break;
    
     case 1:

       functArr[chan] = &LEFT_PED_INV;
       break;
       
     case 2:  
       functArr[chan] = &RIGHT_PED;
       break;
    
     case 3:

       functArr[chan] = &RIGHT_PED_INV;
       break;         
    }
    bottomval[chan] = old_bottomval[chan];
    bottom_offset[chan] = true;
    old_topval[chan] = topval[chan];            // in case both top and bottom offsts are being set at the same time
}

//***********user interface - set lower offset**********

void Set_Lower_Offset_A(byte chan, byte line)  {     //removes any ofsets and runs original function until chan is hit again
    blink_led[2] = false;
                                 // "B" function then saves the offset after chan is hit
    Save_Lower[chan] = true;
    Serial2.print(line, DEC);
    Serial2.print(" CHAN to SAVE DN");       // almost works......
    if (function[chan]  < 2)  {
      functArr[chan] = &LEFT_PED_LOWER_OFFSET;
      }
    else   {
      functArr[chan] = &RIGHT_PED_LOWER_OFFSET;
      }
     bottomval[chan] = 0;
     bottom_offset[chan] = true; 
}


void Set_Lower_Offset_B(byte chan, byte line) {
  Save_Lower[chan] = false; 
for (i=0; i < 4; i++) {
  if (Save_Lower[i] == true) {      // check neighbours beforee clearing flag
  Set_Lower = true;
    break;
  }
  Set_Lower = false;
}  
  Serial2.print(line, DEC);
  Serial2.print(" Lower Limit SAVED"); 
  clean[chan] = true;      //rub out this text when bargraph displays 
  switch (function[chan]) {
    case 0:  
       functArr[chan] = &LEFT_PED;
       break;
    
     case 1: 
       functArr[chan] = &LEFT_PED_INV;
       break;
       
     case 2:  
       functArr[chan] = &RIGHT_PED;
       break;
    
     case 3:
       functArr[chan] = &RIGHT_PED_INV;
       break;         
    }
    topval[chan] = old_topval[chan];
    top_offset[chan] = true;
    old_bottomval[chan] = bottomval[chan];    // in case both top and bottom offsts are being set at the same time
}
  



//**************** adjust offsets********************

  /* WRITE VOLTAGE BIAS TO ALL CHANNELS
   
   POT A 0-3 are outputs
   POT A 4 - lower POT 0 Bias
   POT A 5 - upper POT 0 Bias
   
   POT B 0 - lower POT 1 Bias
   POT B 1 - upper POT 1 Bias
   POT B 2 - lower POT 2 Bias
   POT B 3 - upper POT 2 Bias
   POT B 4 - lower POT 3 Bias
   POT B 5 - upper POT 3 Bias
   */
   
void Offset_Adjust() {
    if (bottom_offset[0] == true) {              // remainder are top and bottom offsets
       write_pot_a (4, bottomval[0]);            // not one function as the addresses to offset pots are "random"
       bottom_offset[0] = false;                  // mabe use a "case" tp make this more selective?
     }  
 
   if (bottom_offset[1] == true) {
       write_pot_b (0, bottomval[1]);
       bottom_offset[1] = false;
     } 
     
   if (bottom_offset[2] == true) {
       write_pot_b (2, bottomval[2]);
       bottom_offset[2] = false;
     }      
     
   if (bottom_offset[3] == true) {
       write_pot_b (4, bottomval[3]);     
       bottom_offset[3] = false;
     }      
 
   if (top_offset[0] == true) {
       write_pot_a (5, topval[0]);  
       top_offset[0] = false;
     }
     
   if (top_offset[1] == true) {
       write_pot_b (1, topval[1]);
       top_offset[1] = false;
     }
     
   if (top_offset[2] == true) {
       write_pot_b (3, topval[2]); 
       top_offset[2] = false;
     }
     
   if (top_offset[3] == true) {
       write_pot_b (5, topval[3]);
       top_offset[3] = false;
     }
  }   
//*********************** state machine functions*************************

// these functions pass Vout for display only, and to SPI device channels 1-4 ---> 


void RIGHT_PED(int channel) {                      //RIGHT PEDAL output function                       
  wave_channel[channel] = 0;
  if (encoder0Pos != old_encoder0Pos[channel]) 
  {
  Vout[channel] = (((topval[channel] - bottomval[channel]) * encoder0Pos) / 127) + bottomval[channel];              
  MIDIVout[channel] = true;
//  VoutCR[channel] = 2;
  potval = encoder0Pos * 2;                       //to SPI device  
  write_pot_a(channel, potval); 
  old_encoder0Pos[channel] = encoder0Pos;
  }
}

void RIGHT_PED_INV(int channel) {                      //RIGHT PEDAL inverted output function                    
  wave_channel[channel] = 0;
  if (encoder0Pos != old_encoder0Pos[channel]) 
  {
  Vout[channel] = (((topval[channel] - bottomval[channel]) * abs(encoder0Pos - 127)) / 127) + bottomval[channel];           
  MIDIVout[channel] = true;
//  VoutCR[channel] = 2;
  potval = abs((encoder0Pos - 127)*2);                 
  write_pot_a(channel, potval);   
  old_encoder0Pos[channel] = encoder0Pos;
  }
}

void LEFT_PED(int channel) {                      //LEFT PEDAL output function     
  wave_channel[channel] = 0;
  if (encoder1Pos != old_encoder1Pos[channel]) 
  {
  Vout[channel] = (((topval[channel] - bottomval[channel]) * encoder1Pos) / 127) + bottomval[channel];             
  MIDIVout[channel] = true;
//  VoutCR[channel] = 2;
  potval = encoder1Pos * 2;                   
  write_pot_a(channel, potval);    
  old_encoder1Pos[channel] = encoder1Pos;
  }
}

void LEFT_PED_INV(int channel) {                      //LEFT PEDAL inverted output function     
  wave_channel[channel] = 0;
  if (encoder1Pos != old_encoder1Pos[channel]) 
  { 
  Vout[channel] = (((topval[channel] - bottomval[channel]) * abs(encoder1Pos - 127)) / 127) + bottomval[channel];            
  MIDIVout[channel] = true;
//  VoutCR[channel] = 2;
  potval = abs((encoder1Pos - 127)*2);                 
  write_pot_a(channel, potval);   
  old_encoder1Pos[channel] = encoder1Pos;
  }
}
//*********************utility functions************************

  

void RIGHT_PED_UPPER_OFFSET(int channel) {
     wave_channel[channel] = 0;
     if (encoder0Pos != old_encoder0Pos[channel])  {
     write_pot_a(channel, 255);      //the centre digital pot is pegged to max, pedal is now adjusting the upper offset pot
    Vout[channel] = max(bottomval[channel] + 20, encoder0Pos*2); // minimum to leave a gap between offsets for bargraph function            
    MIDIVout[channel] = true;
    topval[channel] = Vout[channel];
    top_offset[channel] = true;  
    old_encoder0Pos[channel] = encoder0Pos;
     }
}


void LEFT_PED_UPPER_OFFSET(int channel) {
     wave_channel[channel] = 0;
     if (encoder1Pos != old_encoder1Pos[channel])  {
     write_pot_a(channel, 255); 
    Vout[channel] = max(bottomval[channel]+ 20, encoder1Pos*2);             
    MIDIVout[channel] = true;
    topval[channel] = Vout[channel];
    top_offset[channel] = true;  
    old_encoder1Pos[channel] = encoder1Pos;
     }
}

void RIGHT_PED_LOWER_OFFSET(int channel) {
     wave_channel[channel] = 0;
     if (encoder0Pos != old_encoder0Pos[channel])  {
     write_pot_a(channel, 0); 
         Vout[channel] = min(topval[channel] - 20, encoder0Pos*2); 
//    Vout[channel] = (((topval[channel] - bottomval[channel]) * encoder0Pos) / 127) + bottomval[channel];             
    MIDIVout[channel] = true;
    bottomval[channel] = Vout[channel];
    bottom_offset[channel] = true;  
    old_encoder0Pos[channel] = encoder0Pos;
     }
}

void LEFT_PED_LOWER_OFFSET(int channel) {
     wave_channel[channel] = 0;
     if (encoder1Pos != old_encoder1Pos[channel])  {
     write_pot_a(channel, 0); 
         Vout[channel] = min(topval[channel] - 20, encoder1Pos*2); 
//    Vout[channel] = (((topval[channel] - bottomval[channel]) * encoder1Pos) / 127) + bottomval[channel];             
    MIDIVout[channel] = true;
    bottomval[channel] = Vout[channel];
    bottom_offset[channel] = true;  
    old_encoder1Pos[channel] = encoder1Pos;
    }    
}

void HOLD_CHAN(int channel) {
}

void WAVEOUT(int channel) {
//  if (VoutCR[channel] != 9) {    //test for toggle that LCD wrote a note once, avoid flickering message
//    VoutCR[channel] = 0;
//  }
  wave_channel[channel] = 1;
    if (encoder0Pos != old_encoder0Pos[channel] && HI_LOW_OFFSET[channel] == true) {
    topval[channel] = encoder0Pos *2;
    top_offset[channel] = true;
    old_encoder0Pos[channel] = encoder0Pos;  
    }
    
    if (encoder1Pos != old_encoder1Pos[channel] && HI_LOW_OFFSET[channel] == true) {
    bottomval[channel] = encoder1Pos *2;
    bottom_offset[channel] = true;  
    old_encoder1Pos[channel] = encoder1Pos;
    }  
}

 //******************LIGHT LED************************

 void flash_LED(byte lednum) {

   if (millis() -  last_keypress <  300) {
     PORTF = switchled[lednum];
     blink_disable = true;
   }
   else {
     PORTF = switchled[9];
     blink_disable = false;
     light_led[lednum] = false;
   }
 } 


 int B_ledState = LOW;             // ledState used to set the LED
 unsigned long B_previousMillis = 0;        // will store last time LED was updated

 
 void blink_LED(byte lednum)  {
   // here is where you'd put code that needs to be running all the time.
   // check to see if it's time to blink the LED; that is, is the difference
   // between the current time and last time we blinked the LED bigger than
   // the interval at which we want to blink the LED.
   if (millis() -  B_previousMillis > 200) {
     // save the last time you blinked the LED 
     B_previousMillis = millis();   
     // if the LED is off turn it on and vice-versa:
     if (B_ledState == LOW) {
       B_ledState = HIGH;
     }
     else  
        B_ledState = LOW; 
   }
   if (B_ledState == HIGH)
     PORTF = switchled[lednum];
   if (B_ledState == LOW)
     PORTF = switchled[9];  
 } 
   
//**************** BARGRAPH DISPLAY STUFF*****************************

void BARGRAPH(byte chan) {
    Num_5 = Vout[chan] * 0.07;                   
    if ((curs[chan] > Num_5 && millis() - last_keypress >1000) || disp_bargraph == true){ 
      disp_bargraph = false;
      if (clean[chan] == true) {
      clean[chan] = false;
        Serial2.print("?x02");       //bar forward first is to print over any writing with a bargraph only if needed
      Serial2.print("?y");         
      Serial2.print(chan, DEC);
      bar_fwd();
      }
      Serial2.print("?x20"); 
      Serial2.print("?y");         
      Serial2.print(chan, DEC);
      bar_back();
      curs[chan] = Num_5;
    }
    else if (curs[chan] < Num_5 && millis() - last_keypress >1000 ) {      // change if need be
      if (clean[chan] == true) {
      clean[chan] = false;
      Serial2.print("?x20");    //rub out any printing under... only if needed
      Serial2.print("?y");         
      Serial2.print(chan, DEC);
      bar_back();
      }
      Serial2.print("?x02");       // cursor to beginning of line "chan"
      Serial2.print("?y");     
      Serial2.print(chan, DEC);
      bar_fwd();
      curs[chan] = Num_5;
      }  
   }     


 
 
 // two functions to add / delete bars in bargraph display 
 void bar_fwd () {
          for (int i = 0; i <= Num_5; i++){ 
           Serial2.print("?5");          // print custom character 5 - solid block tiles
//           delay(1);    
          }
  }
 
 void bar_back () {
     for (int i = 17; i>=Num_5; i--){  
         Serial2.print("?b");
//         delay(1);  
     }
 }




//*******************************************************************  
//function to write SPI to digital pots
byte write_pot_a(int address, int value)      // chan 1, 2, 3, 4 output and offsets for chan 1
{
  digitalWrite(SLAVESELECTA,LOW);     
  //2 byte opcode
  cli();
  spi_transfer(address);
  spi_transfer(value);
  digitalWrite(SLAVESELECTA,HIGH); //release chip, signal end transfer
  sei();
}
byte write_pot_b(int address, int value)
{
  digitalWrite(SLAVESELECTB,LOW);            //offset outputs
  //2 byte opcode
  cli();
  spi_transfer(address);
  spi_transfer(value);
  digitalWrite(SLAVESELECTB,HIGH); //release chip, signal end transfer
  sei();
}
// SPI protocol
char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

volatile byte Subdivision_out = 24;
volatile byte Subdivision = 24; //keep track of selector switch position

/**********************************************************
 *             SUBDIVISION for TAP TEMPO                  *  
 **********************************************************/
void subdivide_tap () {
  int Pot_Val_A = analogRead(POT_A);  
  if (Pot_Val_A < 64) {
    Subdivision = 6; 
    Subdivision_out = 96;
  }
  else if(Pot_Val_A < 192) {
    Subdivision = 9; 
    Subdivision_out = 72;
  }
  else if(Pot_Val_A < 320) {
    Subdivision = 12;  
    Subdivision_out = 48;
  }
  else if(Pot_Val_A < 448) {
    Subdivision = 18; 
    Subdivision_out = 36; 
  } 
  else if(Pot_Val_A < 576) {
    Subdivision = 24; 
    Subdivision_out = 24; 
  } 
  else if(Pot_Val_A < 704) {
    Subdivision = 36;
    Subdivision_out = 18;  
  } 
  else if(Pot_Val_A < 832) {
    Subdivision = 48;
    Subdivision_out = 12; 
  }  
  else if(Pot_Val_A < 960) {
    Subdivision = 72; 
    Subdivision_out = 9;
  }
  else {
    Subdivision = 96;  
    Subdivision_out = 3; 
  }
}

///**********************************************************
// *                      MIDI SYNC                         *
// **********************************************************/
//
//
//
//void Sync() {      
//
//  midi_ticks = midi_ticks++;  //increment the two output channels
//  count_sync = count_sync++;   //this count_sync allows value changes at the quarter note
//  if (count_sync == 24 )
//    count_sync = 0;
//
//  if (midi_ticks == Subdivision) {    //reached the # of ticks **** put in Subdivision variable here?
//    tap ();
//    midi_ticks = 0;
//    if (count_sync == 0) //only if we are synched to the beat then accept new value 
//    subdivide_tap();
//  }
//}


//**************************tap tempo stuff***************
//volatile boolean inhibit_LED = false;
int disp_millis_tap_tempo = 0;    //value for display
unsigned long ctr;   //keep from wrapping around during song
unsigned long lastTap = 0; /* when the last tap happened */
void tap()
{
  /* we keep two of these around to average together later */

  if (millis() - lastTap > 100)  //check for garbage bounces
  {
    currentTimer[1] = currentTimer[0];
    if (play_flag == 1) {                    // for midi, use the timimg provided by ISR   
    currentTimer[0] = midi_beat_time - lastTap;
    lastTap = midi_beat_time;
    }
    else {
    currentTimer[0] = millis() - lastTap;
    lastTap = millis();
    }    
    timeoutTime = 0; /* force the trigger to happen immediately - sync and blink! */
    phase = 0;    //synchronize LFO fr mid and toe taps
    if (currentTimer[0] > (currentTimer[1] + 500))
    {
     ctr = 0;
//     phase = 0;    //synchronize LFO fr mid and toe taps
     disp_TAP(); 
     inhibit_LED = true; 
    }
    else 
    {
      ctr++;  
    }
    if (ctr == 3)
    disp_BPM();
    if (ctr > 4)           // after 4 taps, display only the smaller of the milliseconds measured, (higher BPM) or if the BMPis ging down, has to be above a 4 msec threshold 
    {
//      if (play_flag != 1)  //synch LFO on toe taps, not midi    
//phase= 0; //synchronize the LFO during foot taps - but not during midi clock in - just once at start of midi 
      inhibit_LED = false;  //go back to wavetable pulse output
                     
     if ( disp_millis_tap_tempo > ((currentTimer[0] + currentTimer[1]) / 2) || (disp_millis_tap_tempo +4) < ((currentTimer[0] + currentTimer[1]) / 2))  
      disp_BPM();    // MIDI creates a constant stream of taps, this test just keeps from flooding output display
    }
  }
}
void rescheduleTimer()
{
  /* set the timer to go off again when the time reaches the 
   timeout.  The timeout is all of the "currentTimer" values averaged
   together, then added onto the current time.  When that time has been
   reached, the next tick will happen...
   */
  timeoutTime = millis() + ((currentTimer[0] + currentTimer[1])/2);
}

void slowerTap()
{
  /* function to increase time interval of tap by constant tapDelta 
   */
  for (int i = 0; i < 2; i++) {
    int timerInc = currentTimer[i] + tapDelta;
    currentTimer[i] = min(timerInc, 7500);     //  max timer value to end up with 8 BPM  - to work with a divide by 4 in code
  }
}

void fasterTap()
{
  /* function to decrease time interval of tap by constant tapDelta 
   */
  for (int i = 0; i < 2; i++) {
    int timerDec = currentTimer[i] - tapDelta;
    currentTimer[i] = max(timerDec, 35);  // min time value to get a max freq of just less than 30 Hz or 1700 BPM
                                          // code seems to crap out over 1800 BPM, possibly over the sampling freq or something? where is the limit? 
  }
}


byte resume = 0;
void disp_BPM()  {
   BPM = 120000/(currentTimer[0] + currentTimer[1]);
     disp_millis_tap_tempo = (currentTimer[0] + currentTimer[1]) / 2;  //take average for display of milliseconds
     
    if (BPM <= 45)                 //set a percentage of tap time to increase or decrease
      tapDelta = ((currentTimer[0] + currentTimer[1])/2)*.05; 
    else 
      tapDelta = ((currentTimer[0] + currentTimer[1])/2)*.03;  
      
   for (int i = 0; i < 4; i++) {
     if  (wave_channel[i] == 1) {
       Serial2.print("?x12");
       Serial2.print("?y");
       Serial2.print(i, DEC); 
       if (play_flag == 1)
       Serial2.print ("MID:");
       else
       Serial2.print("BPM:"); 
       Serial2.print("?x20");
       Serial2.print("?y");
       Serial2.print(i, DEC);   
       Serial2.print("?b?b?b?b");
       Serial2.print(BPM);
       resume = i + 1;
       break;
     }
   }  
  for (int i = resume; i < 4; i++) {  //does this cause a problem if resume = 3?
    if  (wave_channel[i] == 1) {      //wipes the remaining lines if line is higher (y is smaller) need it here too, if channel changes without new BPM
       Serial2.print("?x20");
       Serial2.print("?y");
       Serial2.print(i, DEC);   
       Serial2.print("?b?b?b?b?b?b?b?b");     
    }
  }   
}
//byte resume = 0;
void disp_TAP()
  {
//   BPM = 120000/(currentTimer[0] + currentTimer[1]);
   for (int i = 0; i < 4; i++) {
     if  (wave_channel[i] == 1) {
       Serial2.print("?x12");
       Serial2.print("?y");
       Serial2.print(i, DEC); 
       Serial2.print("READ BPM"); 
//       Serial2.print("?x20");
//       Serial2.print("?y");
//       Serial2.print(i, DEC);   
//       Serial2.print("?b?b?b?b");
//       Serial2.print(BPM);
       resume = i + 1;
       break;
     }
   }  
  for (int i = resume; i < 4; i++) {  //does this cause a problem if resume = 3?
    if  (wave_channel[i] == 1) {      //wipes the remaining lines if line is higher (y is smaller) 
       Serial2.print("?x20");
       Serial2.print("?y");
       Serial2.print(i, DEC);   
       Serial2.print("?b?b?b?b?b?b?b?b");     
    }
  }   
}

//******************************** MIDI OUT STUFF****************************

 //  outputs MIDI control on channel 0.  Doesn't check to see that
 //  cmd is greater than 127, or that data values are  less than 127:
 void MIDIcntrl(int cmd, int cntrl, int value) {
   Serial3.print(cmd, BYTE);
   Serial3.print(cntrl, BYTE);
   Serial3.print(value, BYTE);
 }
